package com.itstyle.seckill.web;

/**
 * @author lifujun
 * @description: 执行java脚本
 * @date 2024/3/15 15:59
 */
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.itstyle.seckill.common.entity.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchService;
import java.util.Optional;

@Api(tags ="java脚本运行")
@RestController
@RequestMapping("/run")
public class HotReloadScript {

    @ApiOperation(value="运行java片段",nickname="科帮网")
    @PostMapping("/java")
    public Result runJava(@RequestBody JSONObject jsonObject) throws IOException {
        run(jsonObject);
        return Result.ok();
    }


    @SneakyThrows
    public void run(JSONObject jsonObject) throws IOException {
        // 脚本文件路径
        Path scriptTemplatePath = Paths.get("D:\\ideaproject\\gitee\\test\\src\\ScriptTemplate.txt");
        // 脚本文件路径
        Path scriptPath = Paths.get("D:\\ideaproject\\gitee\\test\\src\\Script.java");
        // 脚本编译后的class文件路径
        Path classPath = Paths.get("D:\\ideaproject\\gitee\\test\\src\\Script.class");
        //
        Path classLoadPath = Paths.get("D:\\ideaproject\\gitee\\test\\src");

        // 创建WatchService并注册要监听的事件
        WatchService watcher = FileSystems.getDefault().newWatchService();
        scriptPath.getParent().register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);

        String replaceStr = Optional.ofNullable(jsonObject.getString("script")).orElse("");
        String searchStr = "#script#";

        try{
            FileReader fileReader = new FileReader(scriptTemplatePath.toString());
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line;
            StringBuilder contentBuilder = new StringBuilder();
            while ((line = bufferedReader.readLine())!=null){
                contentBuilder.append(line).append(System.lineSeparator());
            }
            String fileContent = contentBuilder.toString();
            bufferedReader.close();
            String replaceContent = fileContent.replaceAll(searchStr,replaceStr);
            System.out.println(replaceContent);
            FileWriter fileWriter = new FileWriter(scriptPath.toString());
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(replaceContent);
            bufferedWriter.close();
        }catch (IOException e){
            e.printStackTrace();
        }

        // 编译脚本并加载类
        compileScript(scriptPath, classPath);
        URL[] urls = new URL[]{classLoadPath.toUri().toURL()};
        URLClassLoader classLoader = new URLClassLoader(urls);
        Class<?> scriptClass = classLoader.loadClass("Script");

        // 执行脚本方法
        Method[] methods = scriptClass.getMethods();
        Field[] declaredFields = scriptClass.getDeclaredFields();
        Method mainMethod = scriptClass.getMethod("test");
        Object o = scriptClass.newInstance();
        mainMethod.invoke(o);

        // 监听文件变化并热刷
//        while (true) {
//            final WatchKey key = watcher.poll();
//            if (key == null) continue;
//
//            for (WatchEvent<?> event : key.pollEvents()) {
//                if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY) {
//                    Path changedFile = (Path) event.context();
//                    if (changedFile.endsWith("script.java")) {
//                        compileScript(scriptPath, classPath);
//                        classLoader = new URLClassLoader(urls);
//                        scriptClass = classLoader.loadClass("Script");
//                        mainMethod = scriptClass.getMethod("test");
//                        o = scriptClass.newInstance();
//                        mainMethod.invoke(o);
//                    }
//                }
//            }
//
//            key.reset();
//        }
    }

    private static void compileScript(Path scriptPath, Path classPath) throws IOException {
        // 这里使用javac编译脚本，实际应用中可能需要更复杂的编译逻辑
        Process process = Runtime.getRuntime().exec(String.join(" ", "javac", "-d", classPath.getParent().toString(), scriptPath.toString()));
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
